package com.fary.expression.spel.ast;


import com.fary.core.SpringException;
import com.fary.expression.TypedValue;
import com.fary.expression.spel.SpelMessage;

public interface ValueRef {

	TypedValue getValue();

	void setValue(Object newValue);

	boolean isWritable();

	class NullValueRef implements ValueRef {

		static final NullValueRef INSTANCE = new NullValueRef();

		@Override
		public TypedValue getValue() {
			return TypedValue.NULL;
		}

		@Override
		public void setValue(Object newValue) {
			// The exception position '0' isn't right but the overhead of creating
			// instances of this per node (where the node is solely for error reporting)
			// would be unfortunate.
			throw new SpringException(SpelMessage.NOT_ASSIGNABLE);
		}

		@Override
		public boolean isWritable() {
			return false;
		}
	}


	/**
	 * A ValueRef holder for a single value, which cannot be set.
	 */
	class TypedValueHolderValueRef implements ValueRef {

		private final TypedValue typedValue;

		private final SpelNodeImpl node;  // used only for error reporting

		public TypedValueHolderValueRef(TypedValue typedValue, SpelNodeImpl node) {
			this.typedValue = typedValue;
			this.node = node;
		}

		@Override
		public TypedValue getValue() {
			return this.typedValue;
		}

		@Override
		public void setValue(Object newValue) {
			throw new SpringException(SpelMessage.NOT_ASSIGNABLE);
		}

		@Override
		public boolean isWritable() {
			return false;
		}
	}

}